import type { Directive, DirectiveBinding } from "vue";

// export interface TooltipBindingValue {
//   title?: string
// }

const Title: Directive<HTMLElement, string> = {
  // 在元素被插入到 DOM 中时……
  mounted(el: HTMLElement, binding: DirectiveBinding<string>) {
    let offset: keyof HTMLElementTagNameMap["div"] = "offsetWidth";
    let scroll: keyof HTMLElementTagNameMap["div"] = "scrollWidth";

    if (binding.modifiers.multiLine) {
      offset = "offsetHeight";
      scroll = "scrollHeight";
    }
    const updateTitle = () => {
      if (el[offset] < el[scroll]) {
        el.title = binding.value ?? el.textContent ?? "";
      } else {
        el.title = "";
      }
    };

    const config = {
      attributes: true, // 观察属性变动
      childList: true, // 观察子节点变动
      characterData: true, // 观察文本内容变动
      subtree: true, // 观察后代节点
      attributeFilter: ["id", "class", "style"] // 过滤特定属性
    };

    const mutationCallback = (mutationsList: MutationRecord[]) => {
      mutationsList.forEach(() => updateTitle());
    };

    const mutationObserver = new MutationObserver(mutationCallback);
    mutationObserver.observe(el, config);

    const resizeObserver = new ResizeObserver((entries) => {
      entries.forEach((entry) => {
        if (entry.target === el) {
          updateTitle();
        }
      });
    });

    resizeObserver.observe(el);

    // Store observers for later use
    (el as any).mutationObserver = mutationObserver;
    (el as any).resizeObserver = resizeObserver;
  },
  // 组件更新时
  updated(el: HTMLElement, binding: DirectiveBinding<string>) {
    let offset: keyof HTMLElementTagNameMap["div"] = "offsetWidth";
    let scroll: keyof HTMLElementTagNameMap["div"] = "scrollWidth";
    if (binding.modifiers.multiLine) {
      offset = "offsetHeight";
      scroll = "scrollHeight";
    }
    const text = el.textContent ?? "";
    if (el[offset] < el[scroll]) {
      el.title = binding.value ?? text;
    }
  },
  // 指令与元素解绑时
  unmounted(el: HTMLElement) {
    el.removeAttribute("title");
    (el as any).resizeObserver?.unobserve(el);
    (el as any).mutationObserver?.disconnect();
  }
};

export default Title;
